package model2D;

import context.*;

import mainFrame.MainFrame;
import mainFrame.DrawPanel;

import object2D.Object2D;
import object2D.GroupObject;
import object2D.ImageObject;

import org.json.JSONObject;
import org.json.JSONException;

import util.UTM32Grid;
import util.PixelPoint;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.image.ImageObserver;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;

// ********************************************************************
// *** CLASS: Model2D
// ********************************************************************
public class Model2D implements Context.Constants
{ //private static final boolean DEBUG=true; // Overriding Context.Constants.DEBUG
  static final String TAG="model2D.Model2D";
  
  private static final String META_DATA_IDENT="METADATA";	
  private static final String BACKGROUND_IMAGE_IDENT="BACKGROUND";	

  private DrawPanel drawPanel;
  public DrawPanel getDrawPanel() { return(drawPanel); }
  
  private GroupObject rootGroup;
  private ImageObject backgroundImage;  
  public String getName() { return(backgroundImage.getIdent()); }
  public void backgroudImageDialog() { backgroundImage.edit(); }
 
  private GroupObject currentGroup;
  public void setCurrentGroup(GroupObject currentGroup) { this.currentGroup=currentGroup; }
  public GroupObject getCurrentGroup() { return(currentGroup); }
  
  private UTM32Grid grid;
  public UTM32Grid getGrid() { return(grid); }
  public double getCanvasWidth() { return(backgroundImage.getWidth()); }
  public double getCanvasHeight() { return(backgroundImage.getHeight()); }
  
  // ******************************************************************
  // *** CONSTRUCTOR: Model2D
  // ******************************************************************
  public Model2D(DrawPanel drawPanel,Reader reader) throws IOException,JSONException
  { // NOTE: reader may be null meaning a new empty model
	this.drawPanel=drawPanel;
    if(reader==null) // Create New Empty ObjectModel
    { grid=new UTM32Grid(null);
      backgroundImage=new ImageObject(this,new PixelPoint(0,0)); // Will prompt user
      rootGroup=new GroupObject(this);
    }
    else // Create ObjectModel from URL
    { StringBuffer buf=new StringBuffer();
      int c; while((c=reader.read())>=0) buf.append((char)c);
//	  if(DEBUG) Log.d(TAG,"<init>: FILE="+buf);
      JSONObject rootObject=new JSONObject(buf.toString());
      grid=new UTM32Grid(rootObject.getJSONObject(META_DATA_IDENT));
      backgroundImage=new ImageObject(this,rootObject.getJSONObject(BACKGROUND_IMAGE_IDENT));
	  rootGroup=new GroupObject(this,rootObject);
	  if(VERBOSE) printJSON(TAG,"Create ObjectTree from URL: "+getName(),rootObject);
    }
  }
  
  //*******************************************************************
  // *** METHOD: addChild
  //*******************************************************************
  public void addChild(Object2D child)
  { currentGroup.addChild(child);
    MainFrame.repaint(); 
  }
  
  //*******************************************************************
  // *** METHOD: removeChild
  //*******************************************************************
  public void removeChild(Object2D child)
  { currentGroup.removeChild(child);
    MainFrame.repaint(); 
  }
  
  //*******************************************************************
  // *** METHOD: getObject
  //*******************************************************************
  public Object2D getObject(PixelPoint p)
  { if(rootGroup!=null) return(rootGroup.getObject(p));
	return(null);
  }
  
  //*******************************************************************
  // *** METHOD: toObjectTableModel
  //*******************************************************************
  public ObjectTableModel toObjectTableModel() { return(rootGroup.toObjectTableModel()); }

  // ******************************************************************
  // *** METHOD: paint
  // ******************************************************************
  public void paint(Graphics2D g,ImageObserver imageObserver)
  { rootGroup.paint(g,imageObserver); }
  
  // ******************************************************************
  // *** METHOD paintBackground
  // ******************************************************************
  public void paintBackground(final Graphics2D g,ImageObserver imageObserver)
  { backgroundImage.paint(g,imageObserver); }
  
  // ******************************************************************
  // *** METHOD paintGrid
  // ******************************************************************
  public void paintGrid(final Graphics2D g,ImageObserver imageObserver)
  { double canvasWidth=getCanvasWidth();
	double canvasHeight=getCanvasHeight();
	int n=(int)(canvasWidth/grid.getMeshWidthInPixels())+2;
	g.setColor(Color.red);
	g.draw(new Ellipse2D.Double(grid.getOrigoX()-10,grid.getOrigoY()-10,20,20));
	for(int i= -1;i<n;i++)
	{ double y=grid.getOrigoY()+i*grid.getMeshHeightInPixels(); 
	  if(y<canvasHeight) g.draw(new Line2D.Double(0,y,canvasWidth,y));
	}
	n=(int)(canvasHeight/grid.getMeshHeightInPixels())+2;
	g.setColor(Color.blue);
	for(int i= -1;i<n;i++)
	{ double x=grid.getOrigoX()+i*grid.getMeshWidthInPixels();
	  if(x<canvasWidth) g.draw(new Line2D.Double(x,0,x,canvasHeight));
	}
	g.setColor(Color.black);
  }

  //*******************************************************************
  // *** METHOD: printJSON
  //*******************************************************************
  private void printJSON(String tag,String title,JSONObject rootObject)
  {	Log.println("*** "+tag+": "+title+" ********************************************************************************");  
    try { Log.println(rootObject.toString(4)); } catch(JSONException e) {}
	Log.println("**********************************************************************************************");   
  }
  
  //*******************************************************************
  // *** METHOD: writeJSONFile
  //*******************************************************************
  public void writeJSONFile(Writer writer) throws JSONException
  { JSONObject rootObject=rootGroup.toJSONObject();
    rootObject.put(META_DATA_IDENT,grid.toJSONObject());
    rootObject.put(BACKGROUND_IMAGE_IDENT,backgroundImage.toJSONObject());
    if(VERBOSE) printJSON(TAG,"ObjectTree.writeJSONFile",rootObject);
    rootObject.write(writer);
  }  
    
}
